package net.sf.nlp.ltag.extract;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import net.sf.nlp.ltag.data.ExtractedTree;
import net.sf.nlp.ltag.data.LTAGNode;
import net.sf.nlp.ltag.data.LTAGTree;
import net.sf.nlp.ltag.util.LTAG;

public class ExtractLTAG 
{
	
	protected static Logger logger =  Logger.getLogger(ExtractLTAG.class);
	
	public ExtractResult extract(String bractetedTree)
	{
		try
		{
			logger.debug(bractetedTree);
			
			LTAGNode root = LTAG.buildLTAGNodeFromText(bractetedTree, true);
			
			if (root == null)
				return null;
			
			LTAGTree ttree = new LTAGTree();
	    	ttree.setRoot(root);
	    	
	    	String removeNodeTexts = LTAG.postagSetProperties.getProperty(LTAG.POS_DELETE);
	    	String supportPUs = LTAG.postagSetProperties.getProperty(LTAG.POS_PU_SUPPORT);
	    	
	    	removeNodeTexts=new String(removeNodeTexts.getBytes("ISO-8859-1"),"UTF-8"); 
	    	supportPUs=new String(supportPUs.getBytes("ISO-8859-1"),"UTF-8"); 
	    	
	    	ttree.removeNodes(removeNodeTexts, supportPUs);
	    	
	    	if (ttree.getRoot() == null)
	    		return null;
	    	
	    	return extract(ttree);
		}
		catch(Exception ex)
		{
			logger.error(bractetedTree);
			logger.error(ex, ex);
			
		}
		
		return null;
	}
	
	private ExtractResult extract(LTAGTree ttree) throws Exception
	{
		logger.debug(ttree);
		logger.debug(ttree.toLeafString());
		
		if ((ttree.getRoot().getChildren() == null || ttree.getRoot().getChildren().size() == 0)&& ttree.getRoot().getWord() == null)
			return null;
			
		LTAGTree brackedTree = fullyBracket(ttree);
		
		logger.debug(brackedTree.toLeafString());
		if (!ttree.toLeafString().equals(brackedTree.toLeafString()))
		{
			logger.error("The fullyBracket sentence is wrong, please check it.");
			logger.error("The original sentence is " + ttree);
			logger.error("The bracked sentence is " + brackedTree);
			logger.error("the bracked leaf string  is " + brackedTree.toLeafString());
			logger.error("the original leaf string is " + ttree.toLeafString());
		}
		logger.debug(brackedTree);
		
		List<ExtractedTree> etrees = extractTrees(brackedTree);
		
		for (LTAGTree etree : etrees)
		{
			logger.debug(etree.toLTAG());
			etree.validate();
		}
		
		return new ExtractResult(brackedTree, etrees);
	}
	
	private LTAGTree fullyBracket(LTAGTree ttree)
	{
		LTAGTree bracketedTree = ttree.clone();
		LTAGNode root = bracketedTree.getRoot();
		
		fullyBracket(root);
		
		return bracketedTree;
	}
	
	private void fullyBracket(LTAGNode node)
	{
		if (node.getChildren() == null)
			return;
		
		boolean isCoordinatation = mergeComponentsInOneCCGroup(node);
		
		LTAGNode headChild = LTAGRelation.getHeadChildNode(node);
		
		if (headChild == null)
			return;
		
		List<LTAGNode> coordinatationNodes = new ArrayList<LTAGNode>();
		List<LTAGNode> argumentNodes = new ArrayList<LTAGNode>();
		List<LTAGNode> modifierNodes = new ArrayList<LTAGNode>();
		
		for (int index = 0; index <node.getChildren().size(); index++)
		{
			LTAGNode child = node.getChildren().get(index);
			
			fullyBracket(child);
			
			if (isCoordinatation || child.equals(headChild))
				continue;
			
			if (LTAGRelation.isCoordinationNode(child))
				coordinatationNodes.add(child);
			else if (LTAGRelation.isArgumentNode(headChild, child))
				argumentNodes.add(child);
			else if (LTAGRelation.isModifierNode(headChild, child))
				modifierNodes.add(child);
		}
		
		LTAGRelation.validateRelation(headChild, argumentNodes, modifierNodes);
		
		headChild = insertIntermediateNode4Argument(headChild, argumentNodes, modifierNodes);
		insertIntermediateNode4Modifier(headChild, modifierNodes);
	}
	
	private boolean mergeComponentsInOneCCGroup(LTAGNode node)
	{
		List<LTAGNode> coordinatationNodes = new ArrayList<LTAGNode>();
		
		for (int index = 0; index <node.getChildren().size(); index++)
		{
			LTAGNode child = node.getChildren().get(index);
			
			if (LTAGRelation.isCoordinationNode(child))
				coordinatationNodes.add(child);
		}
		
		insertIntermediateNode4Coordinatation(node, coordinatationNodes);
		
		return !coordinatationNodes.isEmpty();
	}
	
	private LTAGNode insertIntermediateNode4Argument(LTAGNode headChild, List<LTAGNode> argumentNodes, List<LTAGNode> modifierNodes)
	{
		if (modifierNodes.size() == 0 || argumentNodes.size() == 0)
			return headChild;
		
		LTAGNode parentNode = headChild.getParent();
		List<LTAGNode> parentChildren = parentNode.getChildren();
		LTAGNode insertedParentNode = new LTAGNode();
		insertedParentNode.setIntermediateNode(true);
		insertedParentNode.setNodeText(parentNode.getNodeText());
		insertedParentNode.setSemanticTag(parentNode.getSemanticTag());
		
		List<LTAGNode> children = new ArrayList<LTAGNode>();
		
		for (LTAGNode child : parentNode.getChildren())
		{
			if (child.equals(headChild) || argumentNodes.contains(child))
			{
				children.add(child);
				child.setParent(insertedParentNode);
			}
		}
		
		int index = parentChildren.indexOf(headChild);
		parentChildren.set(index, insertedParentNode);
		
		for (LTAGNode argumentNode : argumentNodes)
			parentChildren.remove(argumentNode);
		
		insertedParentNode.setChildren(children);
		insertedParentNode.setParent(parentNode);
		
		headChild = insertedParentNode;
		argumentNodes.clear();
		
		return headChild;
	}
	
	private void insertIntermediateNode4Modifier(LTAGNode headChild, List<LTAGNode> modifierNodes)
	{
		if (modifierNodes.size() == 0)
			return;
		
		if (modifierNodes.size() > 1)
		{
			LTAGNode parentNode = headChild.getParent();
			List<LTAGNode> parentChildren = parentNode.getChildren();
			int headIndex = parentChildren.indexOf(headChild);
			
			List<LTAGNode> leftModifierNodes = new ArrayList<LTAGNode>();
			List<LTAGNode> rightModifierNodes = new ArrayList<LTAGNode>();
			
			parentNode.getChildren().remove(headChild);
			
			for (int i = 0; i < modifierNodes.size(); i++)
			{
				LTAGNode modifierNode = modifierNodes.get(i);
				int modifierIndex = parentChildren.indexOf(modifierNode);
				
				if (modifierIndex < headIndex)
					leftModifierNodes.add(modifierNode);
				else
					rightModifierNodes.add(modifierNode);
			}
			
			for (int i = 1; i < leftModifierNodes.size(); i++)
				parentNode.getChildren().remove(leftModifierNodes.get(i));
			
			int right = rightModifierNodes.size() - 2;
			if (leftModifierNodes.size() > 0)
				right = rightModifierNodes.size() - 1;
			
			for (int i = right; i >= 0; i--)
				parentNode.getChildren().remove(rightModifierNodes.get(i));
			
			for (int i = 1; i < leftModifierNodes.size(); i++)
			{
				LTAGNode modifierNode = leftModifierNodes.get(i);
				
				LTAGNode insertedNode = new LTAGNode();
				List<LTAGNode> children = new ArrayList<LTAGNode>();
				
				children.add(modifierNode);
				modifierNode.setParent(insertedNode);
				
				insertedNode.setIntermediateNode(true);
				insertedNode.setNodeText(parentNode.getNodeText());
				insertedNode.setSemanticTag(parentNode.getSemanticTag());
				insertedNode.setParent(parentNode);
				insertedNode.setChildren(children);
				
				parentNode.getChildren().add(insertedNode);
				parentNode = insertedNode;
			}
			
			for (int i = right; i >= 0; i--)
			{
				LTAGNode modifierNode = rightModifierNodes.get(i);
				
				LTAGNode insertedNode = new LTAGNode();
				List<LTAGNode> children = new ArrayList<LTAGNode>();
				
				children.add(modifierNode);
				modifierNode.setParent(insertedNode);
				
				insertedNode.setIntermediateNode(true);
				insertedNode.setNodeText(parentNode.getNodeText());
				insertedNode.setSemanticTag(parentNode.getSemanticTag());
				insertedNode.setParent(parentNode);
				insertedNode.setChildren(children);
				
				if (modifierNodes.size() == rightModifierNodes.size() || (leftModifierNodes.size() > 0 && i < right))
					parentNode.getChildren().add(0, insertedNode);
				else
					parentNode.getChildren().add(insertedNode);
				
				parentNode = insertedNode;
			}
			
			headChild.setParent(parentNode);
			
			if (modifierNodes.size() == leftModifierNodes.size())
				parentNode.getChildren().add(headChild);
			else
				parentNode.getChildren().add(0, headChild);
		}
		
		insertIntermediateNode4TerminatedHeadNode(headChild);
	}
	
	private void insertIntermediateNode4TerminatedHeadNode(LTAGNode headChild)
	{
		if (headChild.getChildren() != null && headChild.getChildren().size() > 0)
			return;
		
		LTAGNode insertedNode = new LTAGNode();
		insertedNode.setIntermediateNode(true);
		
		LTAGNode parentNode = headChild.getParent();
		
		List<LTAGNode> parentChildren = parentNode.getChildren();
		List<LTAGNode> children = new ArrayList<LTAGNode>();
		
		children.add(headChild);
		
		int index = parentChildren.indexOf(headChild);
		parentChildren.set(index, insertedNode);
		
		insertedNode.setNodeText(parentNode.getNodeText());
		insertedNode.setSemanticTag(parentNode.getSemanticTag());
		insertedNode.setParent(parentNode);
		insertedNode.setChildren(children);
	}
	
	private void insertIntermediateNode4Coordinatation(LTAGNode parentNode, List<LTAGNode> coordinatationNodes)
	{
		List<LTAGNode> parentChildren = parentNode.getChildren();
		List<Integer> mergeGroupIndex = new ArrayList<Integer>();
		
		int lastIndex = 0;
		for (int i = 0; i < coordinatationNodes.size(); i++)
		{
			LTAGNode coordinatationNode = coordinatationNodes.get(i);
			int index = parentChildren.indexOf(coordinatationNode);
			
			if (index - lastIndex > 0)
			{
				mergeGroupIndex.add(lastIndex);
				mergeGroupIndex.add(index);
			}
			
			if (i == coordinatationNodes.size() - 1 && parentChildren.size() - index > 1)
			{
				mergeGroupIndex.add(index + 1);
				mergeGroupIndex.add(parentChildren.size());
			}
			
			lastIndex = index + 1;
		}
		
		for (int i = mergeGroupIndex.size() - 1; i >= 0; i--,i--)
		{
			if (mergeGroupIndex.get(i) - mergeGroupIndex.get(i - 1) < 2)
				continue;
			
			LTAGNode insertedNode = new LTAGNode();
			
			List<LTAGNode> children = new ArrayList<LTAGNode>();
			insertedNode.setIntermediateNode(true);
		
			for (int j = mergeGroupIndex.get(i) - 1; j >= mergeGroupIndex.get(i - 1); j--)
			{
				LTAGNode node = parentChildren.remove(j);
				children.add(0, node);
				node.setParent(insertedNode);
			}
		
			insertedNode.setNodeText(parentNode.getNodeText());
			insertedNode.setSemanticTag(parentNode.getSemanticTag());
			insertedNode.setParent(parentNode);
			insertedNode.setChildren(children);
			
			parentChildren.add(mergeGroupIndex.get(i - 1), insertedNode);
		}
		
		int group = mergeGroupIndex.size() / 2;
		for (int i = 0; i < group - 2; i++)
		{
			LTAGNode insertedNode = new LTAGNode();
			
			List<LTAGNode> children = new ArrayList<LTAGNode>();
			
			insertedNode.setIntermediateNode(true);
			insertedNode.setNodeText(parentNode.getNodeText());
			insertedNode.setSemanticTag(parentNode.getSemanticTag());
			insertedNode.setParent(parentNode);
			insertedNode.setChildren(children);
			
			Iterator<LTAGNode> it = parentNode.getChildren().iterator();
			
			int count = 0;
			while (it.hasNext())
			{
				LTAGNode child = it.next();
				count++;
				
				if (count <= 2)
					continue;
				
				children.add(child);
				child.setParent(insertedNode);
				
				it.remove();
			}
			
			parentNode.getChildren().add(insertedNode);
			
			parentNode = insertedNode;
		}
	}
	
	private List<ExtractedTree> extractTrees(LTAGTree brackedTree) throws Exception
	{
		List<ExtractedTree> eTrees = new ArrayList<ExtractedTree>();
		
		ExtractedTree firstEtree= ExtractedTree.copyFrom(brackedTree);
		firstEtree.setBeginning(true);
		
		eTrees.add(firstEtree);
		
		for (int i = 0; i < eTrees.size(); i++)
		{
			ExtractedTree etree = eTrees.get(i);
			extractTrees(etree, etree.getRoot(), eTrees);
		}
		
		doAfterExtratced(eTrees);
		
		return eTrees;
	}
	
	private void extractTrees(ExtractedTree etree, LTAGNode node, List<ExtractedTree> eTrees) throws Exception
	{
		if (node.getChildren() == null || node.getChildren().size() == 0)
		{
			if (node.getWord() != null)
				node.setType("#");
			
			return;
		}
		
		if (extractCoordinateTree(etree, node, eTrees))
			return;
		
		LTAGNode headChild = LTAGRelation.getHeadChildNode(node);
		
		if (headChild == null)
		{
			logger.warn("The node[" + node.getNodeText() + "] can not find head child!");
			return;
		}
		
		if ("*".equals(headChild.getType()))
		{
			if (node.getChildren().indexOf(headChild) == 0)
				headChild = node.getChildren().get(1);
			else
				headChild = node.getChildren().get(0);
		}
		
		Iterator<LTAGNode> it = node.getChildren().iterator();
		while (it.hasNext())
		{
			LTAGNode child = it.next();
			
			if ("*".equals(child.getType()) || "$".equals(child.getType()))
				continue;
			
			if (child.equals(headChild))
				extractTrees(etree, child, eTrees);
			else if (LTAGRelation.isArgumentNode(headChild, child))
				eTrees.add(generateInitTree(etree, child));
			else if (LTAGRelation.isModifierNode(headChild, child))
			{
				eTrees.add(generateAuxiliaryTree(etree, headChild, child));
				
				it.remove();
			}
		}
	}
	
	private boolean extractCoordinateTree(ExtractedTree etree, LTAGNode node, List<ExtractedTree> eTrees) throws Exception
	{
		boolean coordinateTree = false;
		
		for (int index = 0; index < node.getChildren().size(); index++)
		{
			LTAGNode child = node.getChildren().get(index);
			
			if (!LTAGRelation.isCoordinationNode(child))
				continue;
			
			if (node.getChildren().size() != 3)
			{
				if (node.getChildren().size() == 4 && index == 1 &&  
					LTAGRelation.isCoordinationNode(node.getChildren().get(index + 1)))
				{
					child = node.getChildren().get(index + 1);
					node.getChildren().remove(index);
				}
				else if (node.getChildren().size() == 5 && index == 1 &&  
						LTAGRelation.isCoordinationNode(node.getChildren().get(index + 1)) && 
						LTAGRelation.isCoordinationNode(node.getChildren().get(index + 2)))
				{
						child = node.getChildren().get(index + 2);
						node.getChildren().remove(index);
						node.getChildren().remove(index + 1);
				}
				else
					throw new Exception("The tree has some wrong, since the root of cooridnate tree should has 3 children!");
			}
			
			if (index != 1)
				throw new Exception("The tree has some wrong, the cooridnate node should at mid position!");
			
			LTAGNode midNode = node.getChildren().get(1);
			if ((midNode.getChildren() == null || midNode.getChildren().size() == 0) && midNode.getWord() != null)
				midNode.setType("#");
			 
			LTAGNode firstNode = node.getChildren().get(0);
			LTAGNode lastNode = node.getChildren().get(2);
			
			eTrees.add(generateInitTree(etree, firstNode));
			eTrees.add(generateInitTree(etree, lastNode));
			
			coordinateTree = true;
		}
		
		return coordinateTree;
	}
	
	private ExtractedTree generateInitTree(ExtractedTree etree, LTAGNode substitutionNode)
	{
		ExtractedTree initTree = new ExtractedTree();
		
		etree.addOperatorMap(substitutionNode, initTree);
		
		LTAGNode root = substitutionNode.clone();
		root.setParent(null);
		initTree.setRoot(root);
		substitutionNode.setType("$");
		substitutionNode.setChildren(null);
		substitutionNode.setWord(null);
		
		if (root.getWord() == null)
			return initTree;
		
		Iterator<String> phrases = LTAG.phrasesMap.keySet().iterator();
		while (phrases.hasNext())
		{
			String phrase = phrases.next();
			String phrasePos = LTAG.phrasesMap.get(phrase);
			
			if (phrasePos.contains(substitutionNode.getNodeText() + LTAG.SEPERATOR))
			{
				substitutionNode.setNodeText(phrase);
				
				LTAGNode parent = new LTAGNode();
				List<LTAGNode> children = new ArrayList<LTAGNode>();
				children.add(root);
				
				parent.setNodeText(phrase);
				parent.setChildren(children);
				
				root.setParent(parent);
				initTree.setRoot(parent);
			}
		}
		
		return initTree;
	}
	
	private ExtractedTree generateAuxiliaryTree(ExtractedTree etree, LTAGNode headNode, LTAGNode modifierNode) throws Exception
	{
		LTAGNode parentNode = headNode.getParent();
		
		if (parentNode.getChildren().size() < 2)
			throw new Exception("The tree has some wrong, since the root of modifier tree should has only two child!");
		
		int headIndex = parentNode.getChildren().indexOf(headNode);
		int modifierIndex = parentNode.getChildren().indexOf(modifierNode);
		ExtractedTree auxTree = new ExtractedTree();
		
		etree.addOperatorMap(headNode, auxTree);
		
		LTAGNode root = parentNode.clone();
		root.setParent(null);
		if (headNode.getWord() == null)
			root.setNodeText(headNode.getNodeText());
		else 
			root.setNodeText(headNode.getParent().getNodeText());
		root.setSemanticTag(headNode.getSemanticTag());
		auxTree.setRoot(root);
		
		LTAGNode modifier = root.getChildren().get(modifierIndex);
		LTAGNode foot = root.getChildren().get(headIndex);
		foot.setType("*");
		foot.setChildren(null);
		
		Iterator<LTAGNode> i = root.getChildren().iterator();
		while (i.hasNext())
		{
			LTAGNode temp = i.next();
			
			if (temp.equals(modifier) || temp.equals(foot))
				continue;
			
			i.remove();
		}
		
		return auxTree;
	}
	
	
	private void doAfterExtratced(List<ExtractedTree> eTrees)
	{
		for (ExtractedTree etree : eTrees)
		{
			etree.deleteDuplicatedNodes();
			etree.generateNoAdjunctNode();
		}
	}
	
	
	public static void main(String[] args)
	{
		//URL logURL = LTAGParser.class.getClassLoader().getResource("log4j_parser.properties");
		//PropertyConfigurator.configure(logURL);
		
		
		//String bractetedTree = "( (IP (PP (P 对)  (NP (PN 此))) (PU ，) (NP-PN-SBJ (NR 浦东)) (VP (VP (ADVP (AD 不)) (VP (VC 是)  (VP (DVP (VP (VA 简单))  (DEV 的)) (VP (VV 采取)  (NP-OBJ (CP-APP (IP (NP-SBJ (-NONE- *PRO*))  (VP (PU “)  (VP (VV 干)   (NP-EXT (QP (CD 一)   (CLP (M 段)))  (NP (NN 时间))))  (PU ，)  (VP (PP (P 等)   (LCP (IP (NP-SBJ (-NONE- *pro*))  (VP (VV 积累)  (AS 了)  (NP-OBJ (NN 经验)))) (LC 以后)))  (ADVP (AD 再))  (VP (VP (VV 制定)  (NP-OBJ (NN 法规) (NN 条例)))))  (PU ”)))  (DEC 的))  (NP (NN 做法)))))))  (PU ，)  (CC 而)  (VP (VC 是)  (VP (VP (VV 借鉴)  (NP-OBJ (DNP (NP (NP (ADJP (JJ 发达))  (NP (NN 国家)))  (CC 和)  (NP (NP-PN-APP (NR 深圳) (ETC 等))  (NP (NN 特区))))    (DEG 的))  (NP (NN 经验)  (NN 教训))))  (PU ，)  (VP (VV 聘请)  (NP-OBJ (NP (NN 国内外))  (ADJP (JJ 有关))    (NP (NN 专家)  (NN 学者))))  (PU ，)  (VP (DVP (ADVP (AD 积极)  (PU 、) (AD 及时))  (DEV 地))  (VP (VP (VV 制定)   (NP-OBJ (-NONE- *RNR*-1)))  (CC 和) (VP (VV 推出)    (NP-OBJ-1 (NN 法规性) (NN 文件))))) (PU ，) (VP (VV 使)   (NP-OBJ (DP (DT 这些))  (NP (NN 经济)  (NN 活动))) (IP (NP-SBJ (-NONE- *PRO*)) (VP (VP (ADVP (AD 一)) (VP (VV 出现)))    (VP (ADVP (AD 就)) (VP (SB 被) (VP (VV 纳入)   (NP-OBJ (NN 法制)   (NN 轨道)))))))))))  (PU 。)) )  ";
		//String bractetedTree = " ( (IP (IP (NP-SBJ (PN 双方)) (VP (PP-LOC (P 在)     (NP-PN (NR 北京)     (PU 、)    (NR 巴黎)  (PU 、)     (NR 日内瓦)))    (ADVP (AD 已经))      (VP (VV 进行)  (AS 了) (NP-OBJ (QP (CD 多)      (CLP (M 次)))  (UCP (CP (WHNP-1 (-NONE- *OP*)) (IP (NP-TPC (-NONE- *T*-1))	       (NP-SBJ (NN 气氛))     (VP (VA 友好))))      (CC 和)       (DNP (ADJP (JJ 建设性))  (DEG 的))) (NP (NN 谈判))))))   (PU ，)  (IP (NP-TMP (NT 目前)) (NP-SBJ (-NONE- *pro*)) (VP (ADVP (AD 还))     (VP (VE 有)(IP (NP-SBJ (QP (CD 一些))   (DNP (ADJP (JJ 技术性))   (DEG 的))    (NP (NN 问题)))  (VP (VV 有待于)  (IP-OBJ (NP-SBJ (-NONE- *pro*))  (VP (VV 解决))))))))   (PU 。))) ";
		String bractetedTree ="( (IP (NP-SBJ (PN 它))                                                                    "+
				"         (VP (ADVP (AD 其实))                                                             "+
				"             (VP (VC 是)                                                                  "+
				"                 (VP (ADVP (AD 再次))                                                     "+
				"                     (VP (VV 点燃)                                                        "+
				"                         (AS 了)                                                          "+
				"                         (NP-OBJ (QP (CD 一)                                              "+
				"                                     (CLP (M 场)))                                        "+
				"                                 (CP (WHNP-1 (-NONE- *OP*))                               "+
				"                                     (CP (IP (NP-SBJ (-NONE- *T*-1))                      "+
				"                                             (VP (VP (ADVP (AD 既))                       "+
				"                                                     (VP (VV 让)                          "+
				"                                                         (NP-OBJ (NN 人))                 "+
				"                                                         (IP (NP-SBJ (-NONE- *PRO*))      "+
				"                                                             (VP (VV 心碎)))))            "+
				"                                                 (VP (ADVP (AD 又))                       "+
				"                                                     (VP (VA 棘手)))))                    "+
				"                                         (DEC 的)))                                       "+
				"                                 (NP (NN 辩论)))))))                                      "+
				"         (PU ．)))                                                                        ";
		//String bractetedTree ="( (FRAG  (NN 新华社)  (NR 上海)  (NT 二月) (NT 十日) (NN 电) (PU （) (NN 记者) (NR 谢金虎) (PU 、)  (NR 张持坚)  (PU ）) )) ";
		//String bractetedTree = "(IP (NP-SBJ (NN中资) VP (ADVP (AD已) VP (VV成为 NP-OBJ (NP-PN (NR澳门) CP (WHNP-1 (-NONE-*OP*) CP (IP (NP-SBJ (-NONE-*T*) VP (ADVP (AD最) VP (VA大))) DEC的)) ADJP (JJ外来) NP (NN投资者)))) PU。))";
		//String bractetedTree = "(IP (NP-SBJ (NN 中资))(VP (ADVP (AD 已))(VP (VV 成为)(NP-OBJ (NP-PN (NR 澳门))(CP (WHNP-1 (-NONE- *OP*))(CP (IP (NP-SBJ (-NONE- *T*-1))(VP (ADVP (AD 最))(VP (VA 大))))(DEC 的)))(ADJP (JJ 外来))(NP (NN 投资者)))))(PU 。))";
		ExtractLTAG extract = new ExtractLTAG();
		
		try {
			extract.extract(bractetedTree);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
